
namespace Behemoth.Web.UI {

    using System;
    using System.Collections;
    //using System.Collections.Generic;
    using System.Text;
    using System.Web.UI;
    using System.Web.UI.WebControls;

	public delegate void DataSourceViewEventHandler( object sender, DataSourceViewEventArgs e );
	public class DataSourceViewEventArgs : EventArgs {
		//public readonly int TheNumber;
		//public DivBySevenEventArgs( int num ) {
		//	TheNumber = num;
		//}
	}

	/// <summary>
	/// Simplifies the multi-threaded model for DataSourceControl and
	/// DataSourceView. Especially useful for annoyingly written objects
	/// like those that are included in the SharePoint API.
	/// </summary>
	public class DataSourceViewManager {

		public DataSourceViewManager( IDataSource dataSource ) {
			_dataSource = dataSource;
		}

		#region Properties

		private IDataSource _dataSource;
		public IDataSource Control {
			get { return _dataSource; }
		}

		private DataSourceView _view;
		public DataSourceView DataSourceView {
			get { return _view; }
		}
		
		private string _viewName;
		/// <summary>
		/// Name of the requested view
		/// </summary>
		public string ViewName {
			get { return _viewName; } 
		}

		private IEnumerable _data;
		/// <summary>
		/// if requested, contains the underlying data structure
		/// </summary>
		public IEnumerable Data {
			get { return _data; }
		}

		private bool _dataLoaded = false;
		/// <summary>
		/// Flag that indicates if the data load was completed
		/// </summary>
		public bool IsDataLoaded {
			get { return _dataLoaded; }
		}

		#endregion

		public void GetView( DataSourceSelectArguments args, string viewName ) {
			this._view = GetDataSourceView( this._dataSource, viewName );
            this._viewName = viewName; // set only after GetDataSourceView succeeds
            this._view.Select(args, OnDataLoaded);
		}
		public void GetView( DataSourceSelectArguments args ) {
			GetView( args, string.Empty );
		}
		public void GetView( string viewName ) {
			DataSourceSelectArguments args = new DataSourceSelectArguments();
			GetView( args, viewName );
		}
		public void GetView() {
			GetView( string.Empty );
		}

		private void OnDataLoaded( IEnumerable data ) {
			_data = data;
			_dataLoaded = true;
			OnSelected(new DataSourceViewEventArgs());
		}

		/// <summary>
		/// This event is provided to allow you to bind additional functionality to this object.
		/// Fires after a callback from DataSourceView.Select is completed.
		/// </summary>
		public event DataSourceViewEventHandler Selected;
		public void OnSelected( DataSourceViewEventArgs e ) {
			if (Selected != null)
				Selected( this, e );
		}

		public static DataSourceView GetDataSourceView( IDataSource dsc ) {
			return GetDataSourceView( dsc, string.Empty );
		}
		public static DataSourceView GetDataSourceView( IDataSource dsc, string viewName ) {
			IDataSource ds = ((IDataSource)dsc);
			ICollection namesCollection = ds.GetViewNames();
			if (namesCollection.Count == 0)
				return null;
			// aboid problems with typecasting string arrays and other random crap that comes from allowing the providerr to specify the type too broadly
			System.Collections.Generic.List<string> names = new System.Collections.Generic.List<string>();
			foreach (string name in namesCollection) {
				names.Add( name );
			}

			DataSourceView view = null;
			if (string.IsNullOrEmpty( viewName )) {
				view = ds.GetView( names[0].ToString() ); // usually this is "DefaultView"
			} else {
				if (!names.Contains( viewName ))
					throw new IndexOutOfRangeException( string.Format( "The DataSourceControl does not contain a DataSourceView with the specified name '{0}'.", viewName ) );
				view = ds.GetView( viewName );
			}
			return view;
		}

	} // class

} // namespace
